home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / comm / misc / ClipWatch.lha / ClipWatch / Sources / GraphClass.c < prev    next >
C/C++ Source or Header  |  2000-12-29  |  9KB  |  374 lines

  1.  
  2. /* GraphClass by Marc Le Douarain */
  3. /* based on example by Stefan Stuntz */
  4.  
  5.  
  6. /*
  7. ** This is the instance data for our custom class.
  8. */
  9.  
  10. struct GraphClassData
  11. {
  12.     struct Str_AffiTraceGraph * GraphData;
  13. };
  14.  
  15. #define SHOW_GRAPH 0x8022
  16.  
  17. void PrepCoeffForY(struct Str_AffiTraceGraph * Gfx,double ValMini,double ValMaxi,int YMini,int YMaxi)
  18. {
  19.     double a,b;
  20.     a=(double)(YMaxi-YMini)/(double)(ValMaxi-ValMini);
  21.     b=YMini-(a*ValMini);
  22.   Gfx->CoeffAY=a;
  23.     Gfx->CoeffBY=b;
  24. }
  25. int ConvertYValueToPix(struct Str_AffiTraceGraph *Gfx,double Val)
  26. {
  27.     int resY;
  28.   resY=(int)(Gfx->CoeffAY*Val+Gfx->CoeffBY);
  29.   return(resY);
  30. }
  31.  
  32. void PrepCoeffForX(struct Str_AffiTraceGraph * Gfx,time_t ValMini,time_t ValMaxi,int XMini,int XMaxi)
  33. {
  34.     double a,b;
  35.     a=(double)(XMaxi-XMini)/(double)(ValMaxi-ValMini);
  36.     b=XMini-(a*ValMini);
  37.     Gfx->CoeffAX=a;
  38.     Gfx->CoeffBX=b;
  39. }
  40. int ConvertXValueToPix(struct Str_AffiTraceGraph *Gfx,time_t Val)
  41. {
  42.     int resX;
  43.   resX=(int)(Gfx->CoeffAX*Val+Gfx->CoeffBX);
  44.   return(resX);
  45. }
  46.  
  47. void DrawDotted(struct RastPort * rp,int x_end,int y_end)
  48. {
  49.     int i,x_start,y_start,xtaille,ytaille;
  50.     int steps;
  51.     double c_x,c_y;
  52.     x_start=rp->cp_x;
  53.     y_start=rp->cp_y;
  54.     ytaille=y_end-y_start;
  55.     xtaille=x_end-x_start;
  56.     if ( xtaille>=abs(ytaille) )
  57.     {
  58.         steps=xtaille;
  59.         c_x=1;
  60.         c_y=(double)(ytaille)/(double)steps;
  61.     }
  62.     else
  63.     {
  64.         steps=ytaille;
  65.         c_y=1;
  66.         c_x=(double)(xtaille)/(double)steps;
  67.     }
  68.     for(i=0;i<steps;i=i+3)
  69.     {
  70.         Move(rp,(int)(x_start+(double)i*c_x),(int)(y_start+(double)i*c_y));
  71.         Draw(rp,(int)(x_start+(double)i*c_x),(int)(y_start+(double)i*c_y));
  72.     }
  73. }
  74.  
  75. time_t GetRound(time_t Val,time_t Pas)
  76. {
  77.     time_t T;
  78.     T=Val/Pas;
  79.     return(T*Pas+Pas);
  80. }
  81.  
  82. int DrawYScale(struct RastPort * rp,int PxLeft,int PxYMini,int PxYMaxi,double ValYMini,double ValYMaxi)
  83. {
  84.     char tmp[50];
  85.     char tmp2[50];
  86.     int PxDateDeb;
  87.   int DecalagePix;
  88.     int DecalagePix2;
  89. /*    SetAPen(_rp(obj),_dri(obj)->dri_Pens[HIGHLIGHTTEXTPEN]);*/
  90.     sprintf(tmp,"%.4f",ValYMaxi);
  91.     sprintf(tmp2,"%.4f",ValYMini);
  92.     /* Length in pixels */
  93.     DecalagePix=TextLength(rp,tmp,strlen(tmp));
  94.     DecalagePix2=TextLength(rp,tmp2,strlen(tmp2));
  95.     if (DecalagePix2>DecalagePix)
  96.         DecalagePix=DecalagePix2;
  97.     /* Displaying mini and maxi values for Y */
  98.     Move(rp,PxLeft,PxYMaxi+2);
  99.     Text(rp,tmp,strlen(tmp));
  100.     Move(rp,PxLeft,PxYMini+4);
  101.     Text(rp,tmp2,strlen(tmp2));
  102.     PxDateDeb=PxLeft+DecalagePix+4;
  103.     /* Drawing Y Axe */
  104.     Move(rp,PxDateDeb,PxYMaxi);
  105.     Draw(rp,PxDateDeb,PxYMini+3);
  106.     return PxDateDeb;
  107. }
  108.  
  109. void DrawXScale(struct RastPort * rp,struct Str_AffiTraceGraph *Gfx,int PxYMini,int PxDateDeb,int PxDateFin,time_t TpsDeb,time_t TpsFin)
  110. {
  111.     time_t DiffTps;
  112.   time_t Tab[5][3]={{24*3600,3600,1},{2*24*3600,2*3600,1},{7*24*3600,24*3600,2},{31*24*3600,24*3600,3}};
  113.     time_t PasTps=0;
  114.     int AffiEchelleTps=0;
  115.     time_t TpsI;
  116.     int i;
  117. /*    SetAPen(_rp(obj),_dri(obj)->dri_Pens[HIGHLIGHTTEXTPEN]);*/
  118.     /* Scale */
  119.     Move(rp,PxDateDeb-3,PxYMini);
  120.     Draw(rp,PxDateFin,PxYMini);
  121.     /* Size of time */
  122.     DiffTps=TpsFin-TpsDeb;
  123.     PasTps=0;
  124.     for (i=0;i<=3;i++)
  125.     {
  126.         if(DiffTps==Tab[i][0])
  127.         {
  128.             PasTps=Tab[i][1];
  129.             AffiEchelleTps=Tab[i][2];
  130.         }
  131.     }
  132.     /* Graduation */
  133.     if (PasTps)
  134.     {
  135.         TpsI=GetRound(TpsDeb,PasTps);
  136.         do
  137.         {
  138.             int X;
  139.             char TmpD[20],TmpH[20],Grad[50];
  140.             X=ConvertXValueToPix(Gfx,TpsI);
  141.             Move(rp,X,PxYMini-2);
  142.             Draw(rp,X,PxYMini+2);
  143.             convert_long_to_asciidate(TpsI,TmpD,TmpH);
  144.             if (AffiEchelleTps==1)
  145.             {
  146.                 if (TmpH[0]!='0')
  147.                 {
  148.                     Grad[0]=TmpH[0];
  149.                     Grad[1]=TmpH[1];
  150.                     Grad[2]='\0';
  151.                 }
  152.                 else
  153.                 {
  154.                     Grad[0]=TmpH[1];
  155.                     Grad[1]='\0';
  156.                 }
  157.                 Move(rp,X-6,PxYMini+4+8);
  158.                 Text(rp,Grad,strlen(Grad));                    
  159.             }
  160.             if (AffiEchelleTps==2)
  161.             {
  162.                 Grad[0]=TmpD[0];
  163.                 Grad[1]=TmpD[1];
  164.                 Grad[2]=TmpD[2];
  165.                 Grad[3]=TmpD[3];
  166.                 Grad[4]=TmpD[4];
  167.                 Grad[5]='\0';
  168.                 Move(rp,X+10,PxYMini+4+8);
  169.                 Text(rp,Grad,strlen(Grad));
  170.             }
  171.             if (AffiEchelleTps==3)
  172.             {
  173.                 Grad[0]=TmpD[0];
  174.                 Grad[1]=TmpD[1];
  175.                 Grad[2]='\0';
  176.                 Move(rp,X+2,PxYMini+4+8);
  177.                 Text(rp,Grad,strlen(Grad));
  178.             }
  179.             TpsI=TpsI+PasTps;
  180.         }
  181.         while(TpsI<=TpsFin);
  182.     }
  183. }
  184.  
  185. /*
  186. ** OM_SET method, we need to see if someone want to display a graph.
  187. */
  188. SAVEDS ULONG mSet(struct IClass *cl,Object *obj,Msg msg)
  189. {
  190.     struct GraphClassData *Data = INST_DATA(cl,obj);
  191.     struct TagItem *tags,*tag;
  192.  
  193.     for (tags=((struct opSet *)msg)->ops_AttrList;tag=NextTagItem(&tags);)
  194.     {
  195.         switch (tag->ti_Tag)
  196.         {
  197.             case SHOW_GRAPH:
  198.                 if (tag->ti_Data)
  199.                 {
  200.                     Data->GraphData = ((struct Str_AffiTraceGraph *)tag->ti_Data);
  201.                     MUI_Redraw(obj,MADF_DRAWOBJECT); /* redraw ourselves completely */
  202.                 }
  203.                 break;
  204.         }
  205.     }
  206.  
  207.     return(DoSuperMethodA(cl,obj,msg));
  208. }
  209.  
  210.  
  211. /*
  212. ** AskMinMax method will be called before the window is opened
  213. ** and before layout takes place. We need to tell MUI the
  214. ** minimum, maximum and default size of our object.
  215. */
  216. SAVEDS ULONG mAskMinMax(struct IClass *cl,Object *obj,struct MUIP_AskMinMax *msg)
  217. {
  218.     /*
  219.     ** let our superclass first fill in what it thinks about sizes.
  220.     ** this will e.g. add the size of frame and inner spacing.
  221.     */
  222.  
  223.     DoSuperMethodA(cl,obj,msg);
  224.  
  225.     /*
  226.     ** now add the values specific to our object. note that we
  227.     ** indeed need to *add* these values, not just set them!
  228.     */
  229.  
  230.     msg->MinMaxInfo->MinWidth  += 100;
  231.     msg->MinMaxInfo->DefWidth  += 120;
  232.     msg->MinMaxInfo->MaxWidth  += 1280;
  233.  
  234.     msg->MinMaxInfo->MinHeight += 40;
  235.     msg->MinMaxInfo->DefHeight += 90;
  236.     msg->MinMaxInfo->MaxHeight += 800;
  237.  
  238.     return(0);
  239. }
  240.  
  241.  
  242. /*
  243. ** Draw method is called whenever MUI feels we should render
  244. ** our object. This usually happens after layout is finished
  245. ** or when we need to refresh in a simplerefresh window.
  246. ** Note: You may only render within the rectangle
  247. **       _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj).
  248. */
  249.  
  250. SAVEDS ULONG mDraw(struct IClass *cl,Object *obj,struct MUIP_Draw *msg)
  251. {
  252.     struct GraphClassData *Data = INST_DATA(cl,obj);
  253.     struct Str_AffiTraceGraph *Graph;
  254.     int i;
  255.     int PxLeft;
  256.   int PxDateDeb;
  257.   int PxDateFin;
  258.   int PxYMini;
  259.   int PxYMaxi;
  260.  
  261.   double ValYMini=0;
  262.   double ValYMaxi=0;
  263.  
  264.     PxLeft=_mleft(obj)+2;
  265.     PxDateDeb=_mleft(obj)+12;
  266.   PxDateFin=_mright(obj)-5;
  267.     PxYMini=_mbottom(obj)-18;
  268.     PxYMaxi=_mtop(obj)+5;
  269.  
  270.     Graph=Data->GraphData;
  271.     /* Searching minis and maxis */
  272.   if (Graph)
  273.   {
  274.         if (Graph->NbrSamples>0)
  275.         {
  276.             ValYMini=Graph->Valeurs[0];
  277.             ValYMaxi=Graph->Valeurs[0];
  278.             for(i=1;i<Graph->NbrSamples;i++)
  279.             {
  280.                 if (ValYMini>Graph->Valeurs[i])
  281.                     ValYMini=Graph->Valeurs[i]; 
  282.                 if (ValYMaxi<Graph->Valeurs[i])
  283.                     ValYMaxi=Graph->Valeurs[i]; 
  284.             }
  285.       } 
  286.     }  
  287.  
  288.     /*
  289.     ** let our superclass draw itself first, area class would
  290.     ** e.g. draw the frame and clear the whole region. What
  291.     ** it does exactly depends on msg->flags.
  292.     */
  293.  
  294.     DoSuperMethodA(cl,obj,msg);
  295.  
  296.     /*
  297.     ** if MADF_DRAWOBJECT isn't set, we shouldn't draw anything.
  298.     ** MUI just wanted to update the frame or something like that.
  299.     */
  300.  
  301.     if (!(msg->flags & MADF_DRAWOBJECT))
  302.         return(0);
  303.  
  304.     /*
  305.     ** ok, everything ready to render...
  306.     */
  307.  
  308.  
  309.   if (Graph)
  310.   {
  311.         /* Drawing the scales */
  312. SetAPen(_rp(obj),_dri(obj)->dri_Pens[HIGHLIGHTTEXTPEN]);
  313.         if(Graph->NbrSamples>0)
  314.         {
  315.             PrepCoeffForY(Graph,ValYMini,ValYMaxi,PxYMini,PxYMaxi);
  316.             PxDateDeb=DrawYScale(_rp(obj),PxLeft,PxYMini,PxYMaxi,ValYMini,ValYMaxi);
  317.         }
  318.         PrepCoeffForX(Graph,AffiGraphGene.Time32Deb,AffiGraphGene.Time32Fin,PxDateDeb,PxDateFin);
  319.         DrawXScale(_rp(obj),Graph,PxYMini,PxDateDeb,PxDateFin,AffiGraphGene.Time32Deb,AffiGraphGene.Time32Fin);
  320.  
  321.  
  322.       /* Drawing the samples */
  323.         if(Graph->NbrSamples>0)
  324.         {
  325.             int x,y;
  326.             SetAPen(_rp(obj),_dri(obj)->dri_Pens[TEXTPEN]);
  327. //            x=ConvertXValueToPix(TRUE,Graph->Horodates[0],AffiGraphGene.Time32Deb,AffiGraphGene.Time32Fin,PxDateDeb,PxDateFin);
  328. //            y=ConvertYValueToPix(TRUE,Graph->Valeurs[0],ValYMini,ValYMaxi,PxYMini,PxYMaxi);
  329.             x=ConvertXValueToPix(Graph,Graph->Horodates[0]);
  330.             y=ConvertYValueToPix(Graph,Graph->Valeurs[0]);
  331.           Move(_rp(obj),x,y);
  332.             for (i=1;i<Graph->NbrSamples;i++)
  333.             {
  334. //                x=ConvertXValueToPix(FALSE,Graph->Horodates[i],Graph->Horodates[0],Graph->Horodates[Graph->NbrSamples-1],PxDateDeb,PxDateFin);
  335. //                y=ConvertYValueToPix(FALSE,Graph->Valeurs[i],ValYMini,ValYMaxi,PxYMini,PxYMaxi);
  336.                 x=ConvertXValueToPix(Graph,Graph->Horodates[i]);
  337.                 y=ConvertYValueToPix(Graph,Graph->Valeurs[i]);
  338.                 if ( (Graph->Horodates[i]-Graph->Horodates[i-1]) <= 60*60 )
  339.                     Draw(_rp(obj),x,y);
  340.                 else
  341.                     DrawDotted(_rp(obj),x,y);
  342.             }
  343.         }
  344.     }
  345.  
  346.     return(0);
  347. }
  348.  
  349.  
  350. /*
  351. ** Here comes the dispatcher for our custom class. We only need to
  352. ** care about MUIM_AskMinMax and MUIM_Draw in this simple case.
  353. ** Unknown/unused methods are passed to the superclass immediately.
  354. */
  355.  
  356. #ifdef __GNUC__
  357. SAVEDS ASM ULONG MyDispatcher(REG(a0,struct IClass *cl),REG(a2,Object *obj),REG(a1,Msg msg))
  358. #else
  359. SAVEDS ASM ULONG MyDispatcher(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
  360. #endif
  361. {
  362.     switch (msg->MethodID)
  363.     {
  364.         case OM_SET         : return(mSet      (cl,obj,(APTR)msg));
  365.         case MUIM_AskMinMax : return(mAskMinMax(cl,obj,(APTR)msg));
  366.         case MUIM_Draw      : return(mDraw     (cl,obj,(APTR)msg));
  367.     }
  368.  
  369.     return(DoSuperMethodA(cl,obj,msg));
  370. }
  371.  
  372.  
  373.  
  374.